package com.sunday.common.core.gson;

import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.sunday.common.core.utils.DateTimeUtils;

import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Gson构建util
 *
 * @author zsy
 * @since 2022/10/13
 */
public class GsonUtils {

    protected static final Type MAP_STRING_OBJECT_TYPE = new TypeToken<Map<String, Object>>() {
    }.getType();

    /** 初始化时间转换类 */

    /**
     * LocalDateTime 序列化
     */
    public static final JsonSerializer LOCAL_DATE_TIME_SERIALIZER = (JsonSerializer<LocalDateTime>) (src, typeOfSrc, context) ->
            new JsonPrimitive(DateTimeUtils.formatDateTimeMsSplit(src));
    /**
     * LocalDateTime 反序列
     */
    public static final JsonDeserializer LOCAL_DATE_TIME_DESERIALIZER = (JsonDeserializer<LocalDateTime>) (json, typeOfT, context) ->
            DateTimeUtils.convertDateTimeMsSplit(json.getAsJsonPrimitive().getAsString());
    /**
     * LocalDate 序列化
     */
    public static final JsonSerializer LOCAL_DATE_SERIALIZER = (JsonSerializer<LocalDate>) (src, typeOfSrc, context) ->
            new JsonPrimitive(DateTimeUtils.formatDateSplit(src));
    /**
     * LocalDate 反序列
     */
    public static final JsonDeserializer LOCAL_DATE_DESERIALIZER = (JsonDeserializer<LocalDate>) (json, typeOfT, context) ->
            DateTimeUtils.convertDateSplit(json.getAsJsonPrimitive().getAsString());

    /**
     * Map 反序列 - 此方法存在部分问题 在返回时没有特殊进行处理，
     */
    protected static final JsonDeserializer MAP_VALUE_OBJECT_TYPE_DESERIALIZER = (JsonDeserializer<Map<String, Object>>) (json, typeOfT, context) ->
            json.getAsJsonObject().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    /**
     * 默认gson生成策略
     */
    public static final Gson DEFAULT = new GsonBuilder()
            .registerTypeAdapter(Map.class, ObjectTypeAdapter.getInstance())
            .registerTypeAdapter(MAP_STRING_OBJECT_TYPE, ObjectTypeAdapter.getInstance())
            .disableHtmlEscaping()//gson会默认将特殊字符转化成unicode编码
            .create();

    /**
     * 仅打印@Expose注解属性
     */
    public static final Gson EXPOSE = new GsonBuilder()
            .registerTypeAdapter(Map.class, ObjectTypeAdapter.getInstance())
            .registerTypeAdapter(MAP_STRING_OBJECT_TYPE, ObjectTypeAdapter.getInstance())
            .excludeFieldsWithoutExposeAnnotation() //不对没有用@Expose注解的属性进行操作
            .disableHtmlEscaping()//gson会默认将特殊字符转化成unicode编码
            .create();

    /**
     * 时间类型格式化
     */
    public static final Gson DATE_FORMAT = new GsonBuilder()
            .registerTypeAdapter(Map.class, ObjectTypeAdapter.getInstance())
            .registerTypeAdapter(MAP_STRING_OBJECT_TYPE, ObjectTypeAdapter.getInstance())
            .registerTypeAdapter(LocalDateTime.class, LOCAL_DATE_TIME_SERIALIZER)
            .registerTypeAdapter(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER)
            .registerTypeAdapter(LocalDate.class, LOCAL_DATE_SERIALIZER)
            .registerTypeAdapter(LocalDate.class, LOCAL_DATE_DESERIALIZER)
            .disableHtmlEscaping()//gson会默认将特殊字符转化成unicode编码
            .create();

    /**
     * Null值序列化显示
     */
    public static final Gson SERIALIZE_NULL = new GsonBuilder()
            .registerTypeAdapter(Map.class, ObjectTypeAdapter.getInstance())
            .registerTypeAdapter(MAP_STRING_OBJECT_TYPE, ObjectTypeAdapter.getInstance())
            .registerTypeAdapter(LocalDateTime.class, LOCAL_DATE_TIME_SERIALIZER)
            .registerTypeAdapter(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER)
            .registerTypeAdapter(LocalDate.class, LOCAL_DATE_SERIALIZER)
            .registerTypeAdapter(LocalDate.class, LOCAL_DATE_DESERIALIZER)
            .serializeNulls() //当字段值为空或null时，依然对该字段进行转换
            .disableHtmlEscaping()//gson会默认将特殊字符转化成unicode编码
            .create();

}
